// utils/chunkedUploader.js - 简化版分片上传工具
import axios from 'axios'
import { basePythonURL2 } from "@/api";

class ChunkedUploader {
    constructor(options = {}) {
        this.chunkSize = options.chunkSize || 5 * 1024 * 1024 // 5MB per chunk
        this.retryCount = options.retryCount || 3
        this.concurrent = options.concurrent || 3 // 并发上传数
        this.baseURL = `${basePythonURL2}/api`
    }

    /**
     * 分片上传文件
     * @param {File} file - 要上传的文件
     * @param {string} type - 文件类型
     * @param {Function} onProgress - 进度回调 (progress, stage) => {}
     * @returns {Promise}
     */
    async uploadFile(file, type, onProgress = () => {}) {
        try {
            // 1. 初始化上传
            onProgress(0, '初始化上传...')
            const uploadInfo = await this.initUpload(file, type)

            // 2. 分片上传
            onProgress(0, '开始分片上传...')
            await this.uploadChunks(file, uploadInfo, onProgress)

            // 3. 完成上传
            onProgress(95, '合并文件...')
            const result = await this.completeUpload(uploadInfo.uploadId)

            onProgress(100, '上传完成')
            return result
        } catch (error) {
            onProgress(0, `上传失败: ${error.message}`)
            throw error
        }
    }

    /**
     * 初始化上传
     */
    async initUpload(file, type) {
        const response = await axios.post(`${this.baseURL}/upload/init`, {
            filename: file.name,
            fileSize: file.size,
            fileType: type,
            chunkSize: this.chunkSize
        })

        if (!response.data.success) {
            throw new Error(response.data.message || '初始化失败')
        }

        return response.data
    }

    /**
     * 分片上传
     */
    async uploadChunks(file, uploadInfo, onProgress) {
        const chunks = this.createChunks(file)
        const uploadedChunks = new Set(uploadInfo.uploadedChunks || [])

        // 过滤已上传的分片
        const pendingChunks = chunks.filter(chunk => !uploadedChunks.has(chunk.index))

        if (pendingChunks.length === 0) {
            onProgress(90, '所有分片已上传，准备合并...')
            return
        }

        // 控制并发上传
        let completed = 0
        const total = pendingChunks.length

        // 分批上传
        for (let i = 0; i < pendingChunks.length; i += this.concurrent) {
            const batch = pendingChunks.slice(i, i + this.concurrent)
            const promises = batch.map(chunk => this.uploadChunkWithRetry(chunk, uploadInfo.uploadId))

            await Promise.all(promises)
            completed += batch.length

            // 更新进度
            const progress = Math.min(90, (completed / total) * 90)
            onProgress(progress, `上传分片 ${completed}/${total}`)
        }
    }

    /**
     * 创建文件分片
     */
    createChunks(file) {
        const chunks = []
        const totalChunks = Math.ceil(file.size / this.chunkSize)

        for (let i = 0; i < totalChunks; i++) {
            const start = i * this.chunkSize
            const end = Math.min(start + this.chunkSize, file.size)
            const chunk = file.slice(start, end)

            chunks.push({
                index: i,
                data: chunk,
                size: chunk.size,
                start,
                end
            })
        }

        return chunks
    }

    /**
     * 上传单个分片（带重试）
     */
    async uploadChunkWithRetry(chunk, uploadId, retryCount = 0) {
        try {
            await this.uploadChunk(chunk, uploadId)
        } catch (error) {
            if (retryCount < this.retryCount) {
                console.warn(`分片 ${chunk.index} 上传失败，重试 ${retryCount + 1}/${this.retryCount}`)
                await new Promise(resolve => setTimeout(resolve, 1000 * (retryCount + 1)))
                return this.uploadChunkWithRetry(chunk, uploadId, retryCount + 1)
            }
            throw new Error(`分片 ${chunk.index} 上传失败: ${error.message}`)
        }
    }

    /**
     * 上传单个分片
     */
    async uploadChunk(chunk, uploadId) {
        const formData = new FormData()
        formData.append('chunk', chunk.data)
        formData.append('chunkIndex', chunk.index)
        formData.append('uploadId', uploadId)

        const response = await axios.post(`${this.baseURL}/upload/chunk`, formData, {
            headers: {
                'Content-Type': 'multipart/form-data'
            },
            timeout: 60000 // 60秒超时
        })

        if (!response.data.success) {
            throw new Error(response.data.message || '分片上传失败')
        }

        return response.data
    }

    /**
     * 完成上传
     */
    async completeUpload(uploadId) {
        const response = await axios.post(`${this.baseURL}/upload/complete`, { uploadId })

        if (!response.data.success) {
            throw new Error(response.data.message || '完成上传失败')
        }

        return response.data
    }

    /**
     * 取消上传
     */
    async cancelUpload(uploadId) {
        try {
            await axios.post(`${this.baseURL}/upload/cancel`, { uploadId })
        } catch (error) {
            console.warn('取消上传失败:', error)
        }
    }
}

/**
 * 智能上传函数 - 根据文件大小自动选择上传方式
 * @param {File} file - 文件对象
 * @param {string} type - 文件类型
 * @param {Function} onProgress - 进度回调
 * @returns {Promise}
 */
export async function smartUpload(file, type, onProgress = () => {}) {
    const SIZE_THRESHOLD = 100 * 1024 * 1024 // 100MB阈值

    if (file.size > SIZE_THRESHOLD) {
        // 大文件使用分片上传
        console.log(`文件较大 (${(file.size / 1024 / 1024).toFixed(1)}MB)，使用分片上传`)
        const uploader = new ChunkedUploader()
        return uploader.uploadFile(file, type, onProgress)
    } else {
        // 小文件使用传统上传
        console.log(`文件较小 (${(file.size / 1024 / 1024).toFixed(1)}MB)，使用传统上传`)
        return traditionalUpload(file, type, onProgress)
    }
}

/**
 * 传统上传（兼容现有代码）
 */
async function traditionalUpload(file, type, onProgress = () => {}) {
    const formData = new FormData()
    formData.append('file', file)
    formData.append('type', type)

    onProgress(0, '开始上传...')

    const response = await axios.post(`${basePythonURL2}/api/upload`, formData, {
        headers: {
            'Content-Type': 'multipart/form-data'
        },
        timeout: 600000, // 10分钟超时
        onUploadProgress: (progressEvent) => {
            const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total)
            onProgress(progress, '上传中...')
        }
    })

    if (!response.data.success) {
        throw new Error(response.data.message || '上传失败')
    }

    onProgress(100, '上传完成')
    return response.data
}

export default ChunkedUploader
export { ChunkedUploader }